package com.banksoft.cps.service.impl;

import com.banksoft.cps.bean.*;
import com.banksoft.cps.bean.common.ServiceException;
import com.banksoft.cps.bean.http.request.Request;
import com.banksoft.cps.bean.http.response.BaseData;
import com.banksoft.cps.bean.http.response.RowData;
import com.banksoft.cps.bean.query.SaleOrderQuery;
import com.banksoft.cps.bean.warpper.SaleOrderWarpper;
import com.banksoft.cps.constants.ErrorConstant;
import com.banksoft.cps.constants.WebConstant;
import com.banksoft.cps.dao.*;
import com.banksoft.cps.enums.Process;
import com.banksoft.cps.enums.PullFlag;
import com.banksoft.cps.service.DeviceService;
import com.banksoft.cps.service.MonitorProductService;
import com.banksoft.cps.service.SaleOrderService;
import com.banksoft.cps.util.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by rongzhao.zhu on 2018/1/2.
 */
@Service
public class SaleOrderServiceImpl implements SaleOrderService {

    @Autowired
    SaleOrderDao saleOrderDao;
    @Autowired
    DeviceService deviceService;
    @Autowired
    MonitorProductService monitorProductService;
    @Autowired
    CompanyDao companyDao;
    @Autowired
    BuyCompanyDao buyCompanyDao;
    @Autowired
    TransportCompanyDao transportCompanyDao;
    @Autowired
    DeviceDao deviceDao;
    @Autowired
    InvokeInfoDao invokeInfoDao;
    @Autowired
    MonitorValueDao monitorValueDao;
    @Autowired
    FileInfoDao fileInfoDao;
    @Autowired
    OffsetOrderDao offsetOrderDao;
    @Autowired
    PractitionerDao practitionerDao;
    @Autowired
    MonitorValueLoraDao monitorValueLoraDao;

    @Override
    public List<SaleOrder> list(SaleOrderQuery query) {

        return saleOrderDao.list(query);
    }

    @Override
    public List<SaleOrderWarpper> listWarpper(SaleOrderQuery query) {
        List<SaleOrder>  saleOrders = saleOrderDao.list(query);
        Map<String,Company> companyMap = new HashMap<>();
        Map<String,BuyCompany> buyCompanyMap = new HashMap<>();
        Map<String,TransportCompany> transCompanyMap = new HashMap<>();
        Map<String,MonitorValue> monitorValueMap = new HashMap<>();
        Map<String,MonitorValueLora> monitorValueLoraMap = new HashMap<>();

        Map<String,OffsetOrder> offsetOrderMap = new HashMap<>();
        if(!saleOrders.isEmpty()){
           List<String> companyIdList  = new ArrayList<>();
           List<String> buyCompanyIdList  = new ArrayList<>();
           List<String> transCompanyIdList  = new ArrayList<>();
           List<String> saleOrderIdList =  new ArrayList<>();
            saleOrders.forEach(e->{
                if(StringUtils.isNotBlank(e.getCompanyId())&&!companyIdList.contains(e.getCompanyId())){
                    companyIdList.add(e.getCompanyId());
                }
                if(StringUtils.isNotBlank(e.getBuyCompanyId())&&!buyCompanyIdList.contains(e.getBuyCompanyId())){
                    buyCompanyIdList.add(e.getBuyCompanyId());
                }
                if(StringUtils.isNotBlank(e.getTransportCompanyId())&&
                        !transCompanyIdList.contains(e.getTransportCompanyId())){
                    transCompanyIdList.add(e.getTransportCompanyId());
                }
                saleOrderIdList.add(e.getId());
            });
           if(!companyIdList.isEmpty()){
               List<Company> companyList = companyDao.listByIdList(companyIdList);
               if(companyList !=null && companyList.size()>0){
                   companyList.forEach(e->{
                       companyMap.put(e.getId(),e);
                   });
               }
           }
            if(!transCompanyIdList.isEmpty()){
                List<TransportCompany> transportCompanyList = transportCompanyDao.listByIdList(transCompanyIdList);
                if(transportCompanyList !=null && transportCompanyList.size()>0){
                    transportCompanyList.forEach(e->{
                        transCompanyMap.put(e.getId(),e);
                    });
                }
            }
            if(!buyCompanyIdList.isEmpty()){
                List<BuyCompany> buyCompanyList = buyCompanyDao.listByIdList(buyCompanyIdList);
                if(buyCompanyList !=null && buyCompanyList.size()>0){
                    buyCompanyList.forEach(e->{
                        buyCompanyMap.put(e.getId(),e);
                    });
                }
            }
            List<MonitorValue>  monitorValues = monitorValueDao.listBySaleOrderIdList(saleOrderIdList);
            if(!monitorValues.isEmpty()){
                monitorValues.forEach(e->{
                    monitorValueMap.put(e.getSaleOrderId(),e);
                });
            }
            List<MonitorValueLora> monitorValueLoras = monitorValueLoraDao.listBySaleOrderId(saleOrderIdList);
            if(!monitorValueLoras.isEmpty()){
                monitorValueLoras.forEach(e->{
                    monitorValueLoraMap.put(e.getSaleOrderId(),e);
                });
            }
            List<OffsetOrder>  offsetOrders  = offsetOrderDao.listBySaleOrderIdList(saleOrderIdList);

            if(!offsetOrders.isEmpty()){
                offsetOrders.forEach(e->{
                    offsetOrderMap.put(e.getSaleOrderId(),e);
                });
            }
            List<SaleOrderWarpper> warppers = saleOrders.stream().map(e->{
                SaleOrderWarpper w = new SaleOrderWarpper();
                BeanUtils.copyProperties(e,w);
                Company company = companyMap.get(e.getCompanyId());
                if(company !=null ){
                    w.setCompany(company);
                }
                BuyCompany buyCompany = buyCompanyMap.get(e.getBuyCompanyId());
                if(buyCompany !=null ){
                    w.setBuyCompany(buyCompany);
                }
                TransportCompany transportCompany = transCompanyMap.get(e.getTransportCompanyId());
                if(transportCompany !=null ){
                    w.setTransportCompany(transportCompany);
                }
                MonitorValue monitorValue= monitorValueMap.get(e.getId());
                w.setMonitorValue(monitorValue);

                MonitorValueLora  monitorValueLora = monitorValueLoraMap.get(e.getId());
                if(monitorValueLora !=null){
                    monitorValueLora.setCalcValue(
                            StringNumber.mul(monitorValueLora.getValue(),monitorValueLora.getModulus()));
                }
                w.setMonitorValueLora(monitorValueLora);
                OffsetOrder offsetOrder= offsetOrderMap.get(e.getId());
                w.setOffsetOrder(offsetOrder);
                return w;
            }).collect(Collectors.toList());
           return warppers;
        }


        return null;
    }

    @Override
    public long count(SaleOrderQuery query) {
        return saleOrderDao.count(query);
    }

    @Override
    public void save(SaleOrder bean) throws ServiceException {

        String deviceId = bean.getDeviceId();
        try{
            bean.setTimeB(DateUtil.getTime2(bean.getTimeBegin()));
            bean.setTimeE(DateUtil.getTime2(bean.getTimeEnd()));
        }catch (Exception e){
            throw new ServiceException(ErrorConstant.ec_param_error,
                    ErrorConstant.em_date_error);
        }

        if(StringUtils.isNotBlank(deviceId)){
            Device device =  deviceService.findById(deviceId);
            bean.setDeviceName(device.getName());
            String productId = device.getProductId();
            MonitorProduct product = monitorProductService.findById(productId);
            bean.setProductId(productId);
            bean.setProductName(product.getName());
            bean.setUnit(product.getUnit());
        }
        if(StringUtils.isNotBlank(bean.getId())){
            SaleOrder db = saleOrderDao.findById(bean.getId());
            if(Process.auditSuccess.name().equals(db.getProcess()) ){
                throw new ServiceException(ErrorConstant.ec_sale_order_process_error,
                        ErrorConstant.em_sale_order_process_error);
            }
            saleOrderDao.update(bean);
        }else {
            bean.setId(UUIDFactory.random());
            bean.setCreateTime(System.currentTimeMillis());
            bean.setProcess(Process.create.name());
            bean.setPullFlag(PullFlag.n.name());
            saleOrderDao.insert(bean);
        }
    }

    @Override
    public SaleOrder findById(String id) {
        if(StringUtils.isNotBlank(id)){
            return saleOrderDao.findById(id);
        }
        return null;
    }

    @Override
    public SaleOrderWarpper findWarpperById(String id) {
        if(StringUtils.isNotBlank(id)){
            SaleOrderWarpper warpper = new SaleOrderWarpper();
            SaleOrder bean = saleOrderDao.findById(id);
            BeanUtils.copyProperties(bean,warpper);
            Company company =  companyDao.findById(bean.getCompanyId());
            warpper.setCompany(company);
            BuyCompany buyCompany = buyCompanyDao.findById(bean.getBuyCompanyId());
            warpper.setBuyCompany(buyCompany);
            TransportCompany transportCompany = transportCompanyDao.findById(bean.getTransportCompanyId());
            warpper.setTransportCompany(transportCompany);
            MonitorValue monitorValue =  monitorValueDao.findBySaleOrderId(id);
            MonitorValueLora  monitorValueLora = monitorValueLoraDao.findBySaleOrderId(id);
            if(monitorValueLora !=null){
                monitorValueLora.setCalcValue(
                        StringNumber.mul(monitorValueLora.getValue(),monitorValueLora.getModulus()));
            }

            warpper.setMonitorValue(monitorValue);
            warpper.setMonitorValueLora(monitorValueLora);
            if(StringUtils.isNotBlank(bean.getPractitionerDriverId())){
                Practitioner practitioner = practitionerDao.findById(bean.getPractitionerDriverId());
                warpper.setDriver(practitioner);
            }
            if(StringUtils.isNotBlank(bean.getPractitionerSupercargoId())){
                Practitioner practitioner = practitionerDao.findById(bean.getPractitionerSupercargoId());
                warpper.setSupercargo(practitioner);
            }
            String files = bean.getCarImage();
            if (StringUtils.isNotBlank(files)) {
                String[] fileIdsArray = files.split(",");
                List fileIds = Arrays.asList(fileIdsArray);
                List fileInfos = fileInfoDao.queryFiles(fileIds);
                warpper.setCarImageList(fileInfos);
            }
            files = bean.getPeopleImage();
            if (StringUtils.isNotBlank(files)) {
                String[] fileIdsArray = files.split(",");
                List fileIds = Arrays.asList(fileIdsArray);
                List fileInfos = fileInfoDao.queryFiles(fileIds);
                warpper.setPeopleImageList(fileInfos);
            }
            files = bean.getDriverImages();
            if (StringUtils.isNotBlank(files)) {
                String[] fileIdsArray = files.split(",");
                List fileIds = Arrays.asList(fileIdsArray);
                List fileInfos = fileInfoDao.queryFiles(fileIds);
                warpper.setDriverImagesList(fileInfos);
            }
            files = bean.getSupercargoImages();
            if (StringUtils.isNotBlank(files)) {
                String[] fileIdsArray = files.split(",");
                List fileIds = Arrays.asList(fileIdsArray);
                List fileInfos = fileInfoDao.queryFiles(fileIds);
                warpper.setSupercargoImagesList(fileInfos);
            }
            return warpper;
        }

        return null;
    }

    @Override
    public void pullData(String id) throws ServiceException{
        SaleOrder saleOrder = saleOrderDao.findById(id);
        if(saleOrder.getTimeE()> System.currentTimeMillis()){
            throw new ServiceException(ErrorConstant.ec_pull_time_error,ErrorConstant.em_pull_time_error);
        }
        Device device = deviceDao.findById(saleOrder.getDeviceId());
        Request request =  PullDataUtil.buildRequest(saleOrder,device);
        request.setPage("1");
        request.setPageSize("1");
        String param =  JsonUtils.encode(request);
        String  result = HttpClientUtil.sendHttpPostJson(PullDataUtil.url, param);
        BaseData baseDataE = JsonUtils.decode(result, BaseData.class);
        if(PullDataUtil.pullOk.equals(baseDataE.getFlag())){
            InvokeInfo invokeInfo  = InvokeInfoBuiler.build("", "",param,PullDataUtil.url,result);
            invokeInfo.setStatus("ok");
            invokeInfoDao.insert(invokeInfo);
            request.setPage(baseDataE.getTotalPage());
            param =  JsonUtils.encode(request);
            result = HttpClientUtil.sendHttpPostJson(PullDataUtil.url, param);
            BaseData baseDataB = JsonUtils.decode(result, BaseData.class);
            InvokeInfo invokeInfoEnd  = InvokeInfoBuiler.build("", "",param,PullDataUtil.url,result);
            invokeInfoEnd.setStatus("ok");
            invokeInfoDao.insert(invokeInfoEnd);
            if(PullDataUtil.pullOk.equals(baseDataB.getFlag())){
                RowData rowDataE =  baseDataE.getDataList().get(0);
                RowData rowDataB =  baseDataB.getDataList().get(0);
                String val = StringNumber.sub(rowDataE.getVal(),rowDataB.getVal());
                saleOrder.setPullFlag(PullFlag.y.name());
                MonitorValue monitorValue =  new MonitorValue();
                monitorValue.setId(UUIDFactory.random());
                monitorValue.setSaleOrderId(id);
                monitorValue.setCreateTime(System.currentTimeMillis());
                monitorValue.setValue(val);
                monitorValue.setInvokeId(invokeInfo.getId()+ WebConstant.sperator+invokeInfoEnd.getId());
                monitorValueDao.insert(monitorValue);
                saleOrder.setPullFlag(PullFlag.y.name());
                if(StringNumber.compareTo(val,saleOrder.getAmount())==0){
                    saleOrder.setProcess(Process.auditSuccess.name());
                }else {
                    saleOrder.setProcess(Process.auditFail.name());
                }
                saleOrderDao.update(saleOrder);

            }else {
                throw new ServiceException(ErrorConstant.ec_pull_error,ErrorConstant.em_pull_error);
            }
        }else {
            throw new ServiceException(ErrorConstant.ec_pull_error,ErrorConstant.em_pull_error);
        }

    }

    @Override
    public void delete(String[] ids) {
        saleOrderDao.delete(ids);
    }
}
